#include "../lib_include/Buffer.h"
#include "../lib_include/SocketsOps.h"

#include <errno.h>
#include <sys/uio.h>

using namespace netlib;
using namespace netlib::net;

const char Buffer::kCRLF[] = "\r\n"; // 查找标志

const size_t Buffer::kCheapPrepend;
const size_t Buffer::kInitialSize;

// 从套接字中读取数据，保存到缓冲区中
ssize_t Buffer::readFd(int fd, int* savedErrno)
{
    char extrabuf[65536]; // 栈上的缓冲区，争取一次将fd的数据读完，节省系统调用的次数
    struct iovec vec[2]; // readv参数，分散内存块
    const size_t writable = writableBytes();
    vec[0].iov_base = begin()+writerIndex_; // 一块指向自己开辟的动态空间
    vec[0].iov_len = writable;
    vec[1].iov_base = extrabuf; // 一块指向栈上的缓冲区
    vec[1].iov_len = sizeof extrabuf;
    const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1; // 判断两个缓冲区大小
    const ssize_t n = sockets::readv(fd, vec, iovcnt);
    if (n < 0)
        *savedErrno = errno; // 读取失败，设置错误码
    else if (implicit_cast<size_t>(n) <= writable)
        writerIndex_ += n; // 动态缓冲区足够容纳数据，更新可写位置
    else // 一开始尽可能分配少的动态缓冲容量，不够了再扩容，节省资源
    {
        writerIndex_ = buffer_.size();
        append(extrabuf, n - writable); // 超过缓冲区大小的数据，需要扩容
    }
    return n;
}

